 using UnityEngine;
 using System.Collections.Generic;

 public class BM_AudioManager : MonoBehaviour
 {
	public enum AudioPrefs
	{
		AUDIO_NONE
	,	AUDIO_ON
	,	AUDIO_OFF
	}
	
	public enum AudioGroups
	{
		GROUP_FOOTSTEPS
	}
	
	#region Members
	
	private bool 	m_bAudioEnabled;
	private float	m_fSoundFxDefaultVolume = 1.0f;
	
	private int					m_iAudioSourcesPoolSize = 40;
	private string				m_strContainerName = "AudioSourceContainer";
	private string				m_strPrefabName = "AudioSource";
	
	private GameObject			m_rAudioSourcePrefab = null;
	private Stack<AudioSource>	m_vAudioSourcesPool = null;
	private List<AudioSource>	m_vUsedAudioSources = null;	
	
		
	
	private Dictionary<AudioGroups, SFXId[]> m_dictRandomAudioGroups = new Dictionary<AudioGroups, SFXId[]>()
	{
		{ AudioGroups.GROUP_FOOTSTEPS,		m_svRandom_FootSteps }
	};
	
	private static readonly SFXId[] m_svRandom_FootSteps = new SFXId[]
	{
		SFXId.SFX_DUMMY	
	,	SFXId.SFX_DUMMY
	,	SFXId.SFX_DUMMY
	,	SFXId.SFX_DUMMY
	,	SFXId.SFX_DUMMY	
	};
	
	#endregion
	
	
	#region Properties
	
	public float SoundFXVolume
	{
		 get { return m_fSoundFxDefaultVolume; }
		 set { m_fSoundFxDefaultVolume = value; }
	}
	
	public bool NoRinger
	{
		get 
		{
			bool bRVal = false;
			
//			if(CM_SPenPlugin.Instance() != null && !Debug.isDebugBuild)
//				bRVal = !CM_SPenPlugin.Instance().isRingerModeNormal;
			
			return bRVal;
		}
	}
	
	public bool AudioEnabled
	{
		get { return m_bAudioEnabled; }
		
		set
		{
			m_bAudioEnabled = !NoRinger && value;
			AudioListener.volume = m_bAudioEnabled ? 1.0f : 0.0f;
		}
	}
	
	#endregion
	
	
	public void Awake()
	{
		m_rManagerReference = this;
		
		m_rAudioSourcePrefab = (GameObject)Resources.Load(m_strPrefabName);
		
		GameObject rGameManager = GameObject.FindGameObjectWithTag(BM_Common.GetLabelName(StringLabel.LABEL_TAG_GAMEMANAGER));
		GameObject m_rContainer = new GameObject(m_strContainerName);
		m_rContainer.transform.parent = rGameManager.transform;
		
		m_vAudioSourcesPool = new Stack<AudioSource>();
		m_vUsedAudioSources = new List<AudioSource>();
		for(int iSource = 0; iSource < m_iAudioSourcesPoolSize; ++iSource)
		{
			GameObject rSourceObj = (GameObject)GameObject.Instantiate(m_rAudioSourcePrefab);
			rSourceObj.transform.parent = m_rContainer.transform;
			rSourceObj.name = m_strPrefabName+"_"+iSource;
			rSourceObj.SetActive(false);
			
			m_vAudioSourcesPool.Push(rSourceObj.GetComponent<AudioSource>());
		}
	}
	
	public void Start()
	{
		 bool bLoadedSoundsStatus = BM_AppDataManager.Instance().SoundStatus_OnFile;
		 AudioEnabled = bLoadedSoundsStatus;
	}
	
	public void OnDestroy()
	{
		 m_rManagerReference = null;
	 }
	
	 public void Update()
	 {
		 List<AudioSource> vSourcesToRemove = new List<AudioSource>();		
		 foreach(AudioSource rSource in m_vUsedAudioSources)
		 {
			 if(!rSource.isPlaying)
			 {
				 rSource.clip = null;
				 rSource.gameObject.transform.position = Vector3.zero;
				 rSource.gameObject.SetActive(false);
				 vSourcesToRemove.Add(rSource);
			 }
		 }
		
		 foreach(AudioSource rRemove in vSourcesToRemove)
		 {
			 m_vUsedAudioSources.Remove(rRemove);
			 m_vAudioSourcesPool.Push(rRemove);
		 }
		 vSourcesToRemove.Clear();
	 }
	
	
	
	 public void ToggleAudio()
	 {
		 BM_AppDataManager.Instance().SoundStatus_OnFile = !m_bAudioEnabled;
		 AudioEnabled = !AudioEnabled;
		
		 bool bActualAudioStatus = !NoRinger && m_bAudioEnabled;
		 AudioListener.volume = bActualAudioStatus ? 1.0f : 0.0f;
	 }
	
	 public void DisableAudioStatus()
	 {
		 AudioListener.volume = 0.0f;
	 }
	
	 public void RestoreAudioStatus()
	 {
		 AudioEnabled = AudioEnabled;
	 }
	
	 private void PlayAudioSource(SFXId eSFXId, Vector3 vPosition, float fVolumeMultiplier)
	 {
		if(m_vAudioSourcesPool.Count > 0)
		{
			BM_Common.AudioData rAudioData;
			if(BM_AudioData.m_sdictAudioData.TryGetValue(eSFXId, out rAudioData))
			{
				float fTimePassed = Time.time-rAudioData.m_lastPlayTime;
				if (fTimePassed > rAudioData.m_waitTimeBeforePlay)
				{
					AudioSource rAudioSource = m_vAudioSourcesPool.Pop();
					rAudioSource.gameObject.SetActive(true);
					
					rAudioSource.gameObject.transform.position = vPosition;
					rAudioSource.clip = rAudioData.m_audioClip;
					rAudioSource.volume = rAudioData.m_volume*fVolumeMultiplier;
					rAudioSource.maxDistance = rAudioData.m_rolloffDistance;
				
					rAudioSource.Play();
					BM_AudioData.m_sdictAudioData[eSFXId].m_lastPlayTime = Time.time;
					
					m_vUsedAudioSources.Add(rAudioSource);
				}
			}
		}
	}
	
	public void PlaySoundAtPoint(SFXId eSFXId, Vector3 vPosition)
	{
		PlayAudioSource(eSFXId, vPosition, m_fSoundFxDefaultVolume);
	}
	
	public void PlaySoundAtPointFromRandomGroup(AudioGroups eAudioGroup, Vector3 vPosition)
	{
		SFXId[] vRandomSounds = null;
		if(m_dictRandomAudioGroups.TryGetValue(eAudioGroup, out vRandomSounds))
			PlayAudioSource(vRandomSounds[Random.Range(0, vRandomSounds.Length)], vPosition, m_fSoundFxDefaultVolume);
	}
	
	
	 #region Singleton
	
	 private static BM_AudioManager		m_rManagerReference = null;
	
	 public static BM_AudioManager Instance()
	 {
		 if(m_rManagerReference == null)
		 {
			 Debug.LogError("SV_AudioManager.Instance() -> Manager non inizializzato! ERRORE!");
			 Debug.DebugBreak();
		 }
		
		 return m_rManagerReference;
	 }
	
	 #endregion
 }
